package com.junzhiit.nengji.cms.service.impl;

import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.bainaeco.framework.util.EncryptMD5Util;
import com.bainaeco.framework.util.JsonUtil;
import com.junzhiit.nengji.bo.SystemUserBO;
import com.junzhiit.nengji.cms.feign.agent.AgentFeignService;
import com.junzhiit.nengji.cms.service.SystemUserService;
import com.junzhiit.nengji.cms.web.exception.CreateSessionErrorException;
import com.junzhiit.nengji.cms.web.exception.InvalidLoginTokenException;
import com.junzhiit.nengji.cms.web.exception.MobilePhoneCodeErrorException;
import com.junzhiit.nengji.cms.web.exception.MobilePhoneCodeTimeoutException;
import com.junzhiit.nengji.cms.web.exception.MobilePhoneHasUsedException;
import com.junzhiit.nengji.cms.web.exception.PasswordNotMatchException;
import com.junzhiit.nengji.cms.web.exception.ShopNotFoundException;
import com.junzhiit.nengji.cms.web.exception.SystemUserNotFoundException;
import com.junzhiit.nengji.cms.web.util.CMSCodeStatus;
import com.junzhiit.nengji.cms.web.util.Constants;
import com.junzhiit.nengji.cms.web.util.OrderNumberUtils;
import com.junzhiit.nengji.cms.web.util.ViewObjectUtil;
import com.junzhiit.nengji.cms.web.util.rsa.RSACoder;
import com.junzhiit.nengji.cms.web.util.tools.DIYTools;
import com.junzhiit.nengji.cms.web.util.tools.KeyUtil;
import com.junzhiit.nengji.cms.web.vo.DataTablesParamVO;
import com.junzhiit.nengji.cms.web.vo.PhoneCodeVO;
import com.junzhiit.nengji.cms.web.vo.ResultVO;
import com.junzhiit.nengji.cms.web.vo.SystemUserAddVO;
import com.junzhiit.nengji.cms.web.vo.SystemUserEditVO;
import com.junzhiit.nengji.cms.web.vo.SystemUserListVO;
import com.junzhiit.nengji.cms.web.vo.SystemUserRoleListVO;
import com.junzhiit.nengji.cms.web.vo.SystemUserSessionVO;
import com.junzhiit.nengji.cms.web.vo.TreeFunctionVO;
import com.junzhiit.nengji.dao.FunctionDAO;
import com.junzhiit.nengji.dao.RoleDAO;
import com.junzhiit.nengji.dao.RoleFunctionDAO;
import com.junzhiit.nengji.dao.ShopDAO;
import com.junzhiit.nengji.dao.SystemUserDAO;
import com.junzhiit.nengji.dao.SystemUserRoleDAO;
import com.junzhiit.nengji.dao.cache.RoleCacheDAO;
import com.junzhiit.nengji.dao.cache.SystemUserCacheDAO;
import com.junzhiit.nengji.dao.util.DIYKey;
import com.junzhiit.nengji.model.Function;
import com.junzhiit.nengji.model.Role;
import com.junzhiit.nengji.model.RoleFunction;
import com.junzhiit.nengji.model.Shop;
import com.junzhiit.nengji.model.SystemUser;
import com.junzhiit.nengji.model.SystemUserRole;
import com.junzhiit.nengji.model.enums.Is;
import com.junzhiit.nengji.model.enums.ShopStatus;
import com.junzhiit.nengji.model.enums.SystemUserStatus;
import com.junzhiit.nengji.model.enums.SystemUserType;
import com.intranet.transport.object.ResultTO;
import com.intranet.transport.object.SystemUserTO;

@Service
public class SystemUserServiceImpl extends BaseServiceImpl implements SystemUserService {
	
	@Value("${key.private}")
	private String PRIVATE_KEY_PATH;

	@Autowired
	private SystemUserDAO systemUserDAO;

	@Autowired
	private SystemUserCacheDAO systemUserCacheDAO;

	@Autowired
	private ShopDAO shopDAO;

	@Autowired
	private SystemUserRoleDAO systemUserRoleDAO;

	@Autowired
	private FunctionDAO functionDAO;

	@Autowired
	private RoleFunctionDAO roleFunctionDAO;

	@Autowired
	private RoleDAO roleDAO;
	
	@Autowired
	private RoleCacheDAO roleCacheDAO;
	
	@Autowired
	private AgentFeignService agentFeignService;

	@Override
	public Map<String, Object> findAll(DataTablesParamVO dtp, SystemUserListVO systemUserListVO) {
		SystemUserSessionVO systemUserSessionVO = systemUserCacheDAO
				.getHash(DIYKey.getSessionHashKey(systemUserListVO.getSessionId()), SystemUserSessionVO.class);

		SystemUser systemUser = new SystemUser();
		BeanUtils.copyProperties(systemUserListVO, systemUser);
		if (systemUserListVO.getPlatform().equals(systemUserSessionVO.getLoginType())) {
			systemUser.setSafetyLevel(systemUserSessionVO.getSafetyLevel());
		}

		List<SystemUserBO> list = systemUserDAO.findAll(systemUser, dtp.getStart(), dtp.getLength());
		for (SystemUserBO item : list) {
			if (systemUserSessionVO.getSystemUserId().equals(item.getId())) {
				item.setIsCurrentAccount(1);
			} else {
				item.setIsCurrentAccount(0);
			}
		}

		int totalCount = systemUserDAO.getTotalCount(systemUser);
		return ViewObjectUtil.dataTables(list, dtp.getDraw(), totalCount);
	}

	@Override
	public Map<String, Object> findAllByPlatform(DataTablesParamVO dtp, SystemUserListVO systemUserListVO) {
		SystemUser systemUser = new SystemUser();
		BeanUtils.copyProperties(systemUserListVO, systemUser);
		List<SystemUserBO> list = systemUserDAO.findAll(systemUser, dtp.getStart(), dtp.getLength());
		int totalCount = systemUserDAO.getTotalCount(systemUser);
		return ViewObjectUtil.dataTables(list, dtp.getDraw(), totalCount);
	}

	@Override
	public ResultVO add(SystemUserAddVO systemUserAddVO) {
		ResultVO result = new ResultVO();

		if (!systemUserAddVO.getPassword().equals(systemUserAddVO.getConfirmPassword())) {
			throw new PasswordNotMatchException("密码不一致");
		}
		int mobilePhoneCount = systemUserDAO.getMobilePhoneCount(systemUserAddVO.getMobilePhone());
		if (mobilePhoneCount > 0) {
			throw new MobilePhoneHasUsedException("一个手机号码只能注册一个账号");
		}
		SystemUserSessionVO systemUserSessionVO = systemUserCacheDAO
				.getHash(DIYKey.getSessionHashKey(systemUserAddVO.getSessionId()), SystemUserSessionVO.class);
		SystemUser systemUser = new SystemUser();
		systemUser.setSystemId(systemUserSessionVO.getSystemId());
		systemUser.setSafetyLevel(systemUserSessionVO.getSafetyLevel().intValue() + 1);
		String password = EncryptMD5Util.getMD5(systemUserAddVO.getPassword());
		BeanUtils.copyProperties(systemUserAddVO, systemUser, new String[] { "confirmPassword" });
		systemUser.setPassword(password);
		systemUser.setStatus(SystemUserStatus.ACTIVE.toIntStatus());
		systemUser = systemUserDAO.insert(systemUser);
		systemUser.setPassword(null);

		// addRole
		SystemUserRoleListVO systemUserRoleListVO = new SystemUserRoleListVO();
		systemUserRoleListVO.setSystemUserId(systemUser.getId());
		systemUserRoleListVO.setRoleIds(systemUserAddVO.getRoleIds());
		addSystemUserRole(systemUserRoleListVO);

		result.setData(systemUser);
		return result;
	}

	@Override
	public SystemUser findById(String systemUserId) {
		SystemUser systemUser = systemUserDAO.query(systemUserId);
		if (systemUser == null) {
			throw new SystemUserNotFoundException("该用户不存在！");
		}
		systemUser.setPassword(null);
		return systemUser;
	}

	@Override
	public ResultVO edit(String id, SystemUserEditVO systemUserEditVO) {
		ResultVO result = new ResultVO();
		
		SystemUser data = systemUserDAO.findByMobilePhone(systemUserEditVO.getMobilePhone());
		if (data != null && !data.getId().equals(id)) {
			throw new MobilePhoneHasUsedException("该手机已经绑定其他账户");
		}

		SystemUser systemUser=new SystemUser();
		systemUser.setId(id);
		BeanUtils.copyProperties(systemUserEditVO, systemUser);
		systemUserDAO.update(systemUser);
		systemUser.setPassword(null);

		// editRole
		SystemUserRoleListVO systemUserRoleListVO = new SystemUserRoleListVO();
		systemUserRoleListVO.setSystemUserId(id);
		systemUserRoleListVO.setRoleIds(systemUserEditVO.getRoleIds());
		addSystemUserRole(systemUserRoleListVO);

		result.setData(systemUser);
		return result;
	}

	@Override
	public ResultVO updateStatus(String id, Integer status) {
		ResultVO result = new ResultVO();
		Shop shop = shopDAO.query(id);
		if (shop == null) {
			throw new ShopNotFoundException("找不到店铺");
		}
		if (status == SystemUserStatus.INACTIVE.toIntStatus()) {
			shop.setStatus(ShopStatus.STOP.toIntStatus());
			shopDAO.update(shop);
		} else if (status == SystemUserStatus.ACTIVE.toIntStatus()) {
			shop.setStatus(ShopStatus.ACTIVE.toIntStatus());
			shopDAO.update(shop);
		}
		List<SystemUser> list = systemUserDAO.getListBySystemId(id);
		if (list.size() < 0) {
			throw new SystemUserNotFoundException("找不到用户");
		}
		for (SystemUser systemUser : list) {
			systemUser.setStatus(status);
			systemUserDAO.update(systemUser);
		}
		return result;
	}

	@Override
	public ResultVO checkPhone(String mobilePhone) {
		ResultVO result = new ResultVO();
		int mobilePhoneCount = systemUserDAO.getMobilePhoneCount(mobilePhone);
		if (mobilePhoneCount > 0) {
			throw new MobilePhoneHasUsedException("手机号码已被注册");
		}
		return result;
	}

	@Override
	public int addSystemUserRole(SystemUserRoleListVO systemUserRoleListVO) {
		List<SystemUserRole> systemUserRoles = new ArrayList<SystemUserRole>();
		for (String roleId : systemUserRoleListVO.getRoleIds()) {
			SystemUserRole systemUserRole = new SystemUserRole();
			systemUserRole.setRoleId(roleId);
			systemUserRole.setSystemUserId(systemUserRoleListVO.getSystemUserId());
			systemUserRoles.add(systemUserRole);
		}

		systemUserRoleDAO.deleteSystemUserRole(systemUserRoleListVO.getSystemUserId());
		return systemUserRoleDAO.batchInsert(systemUserRoles);
	}

	@Override
	public ResultVO getSystemUserFunctions(String sessionId) {
		ResultVO result = new ResultVO();
		String key = DIYKey.getFunctionStringKey(sessionId);
		String content = systemUserCacheDAO.getString(key);

		if (StringUtils.isBlank(content)) {
			SystemUserSessionVO systemUserSessionVO = systemUserCacheDAO.getHash(DIYKey.getSessionHashKey(sessionId),
					SystemUserSessionVO.class);
			List<Function> list = systemUserDAO.getSystemUserFunctions(systemUserSessionVO.getSystemUserId());
			TreeFunctionVO data=tree(list);
			// create session.
			String json = JsonUtil.toJson(data);
			boolean is = systemUserCacheDAO.addString(key, json);
			if (!is) {
				throw new CreateSessionErrorException("create session error...");
			}
			result.setData(data);
		} else {
			TreeFunctionVO data = JsonUtil.toObject(content, TreeFunctionVO.class);
			result.setData(data);
		}
		return result;
	}

	@Override
	public ResultVO updateSystemUserStatus(String id, int status) {
		ResultVO result = new ResultVO();
		SystemUser systemUser = systemUserDAO.query(id);
		if (systemUser == null) {
			throw new SystemUserNotFoundException("该用户不存在！");
		}
		boolean data = systemUserDAO.updateSystemUserStatus(id, status);
		result.setData(data);
		return result;
	}

	@Override
	public ResultVO initPower(SystemUserAddVO systemUserAddVO) {
		ResultVO result = new ResultVO();

		// 添加用户
		if (!systemUserAddVO.getPassword().equals(systemUserAddVO.getConfirmPassword())) {
			throw new PasswordNotMatchException("密码不一致");
		}
		int mobilePhoneCount = systemUserDAO.getMobilePhoneCount(systemUserAddVO.getMobilePhone());
		if (mobilePhoneCount > 0) {
			throw new MobilePhoneHasUsedException("一个手机号码只能注册一个账号");
		}
		SystemUser systemUser = new SystemUser();
		systemUser.setSafetyLevel(0);
		String password = EncryptMD5Util.getMD5(systemUserAddVO.getPassword());
		BeanUtils.copyProperties(systemUserAddVO, systemUser, new String[] { "confirmPassword" });
		systemUser.setPassword(password);
		systemUser.setStatus(SystemUserStatus.ACTIVE.toIntStatus());
		systemUser = systemUserDAO.insert(systemUser);

		// 添加角色
		Role role = new Role();
		role.setName("系统管理员");
		Long index = roleCacheDAO.incr(DIYKey.getRoleCodeStringKey());
		String code = OrderNumberUtils.getSystemCode(OrderNumberUtils.ROLE_NUMBER_PREFIX, index.intValue());
		role.setCode(code);
		role.setPlatform(SystemUserType.INTERNAL.toIntStatus());
		role.setIsSys(Is.YES.toIntValue());
		role.setIsCommon(Is.YES.toIntValue());
		Role newRole = roleDAO.insert(role);

		// 添加角色功能
		List<RoleFunction> roleFunctions = new ArrayList<RoleFunction>();
		List<Function> functions = functionDAO.findByPlatform(SystemUserType.INTERNAL.toIntStatus());
		for (Function function : functions) {
			RoleFunction rolefunction = new RoleFunction();
			rolefunction.setFunctionId(function.getId());
			rolefunction.setRoleId(newRole.getId());
			roleFunctions.add(rolefunction);
		}
		roleFunctionDAO.batchInsert(roleFunctions);

		// 添加用户角色
		SystemUserRole systemUserRole = new SystemUserRole();
		systemUserRole.setSystemUserId(systemUser.getId());
		systemUserRole.setRoleId(newRole.getId());
		systemUserRoleDAO.insert(systemUserRole);

		return result;
	}

	@Override
	public ResultVO editUser(String id, SystemUserEditVO systemUserEditVO,HttpServletResponse response) {
		ResultVO result=new ResultVO();
		SystemUser systemUser = systemUserDAO.query(id);
		
		// RSA decoder.
		KeyPair KeyPair = KeyUtil.keyPair(PRIVATE_KEY_PATH);
		String systemUserToken = "", systemUserTokenUrl = "";
		try {
			systemUserTokenUrl = DIYTools.URLDecoder(systemUserEditVO.getSystemUserToken());
			systemUserToken = RSACoder.decrypt(systemUserTokenUrl, KeyPair.getPrivate());
		} catch (Exception e) {
			throw new InvalidLoginTokenException("Invalid login token.");
		}
		Map<String, String> content = DIYTools.splitForm(systemUserToken);
		String mobilePhone = content.get("mobilePhone");
		String oldPassword = content.get("oldPassword");
		String password = content.get("password");
		String name = content.get("name");
		String email = content.get("email");
		
		//原密码错误
		if(oldPassword != null){
			String MD5oldPassword = EncryptMD5Util.getMD5(oldPassword);
			if(!systemUser.getPassword().equals(MD5oldPassword)){
				throw new PasswordNotMatchException("原密码错误");
			}
		}
		
		
		//不更换手机
		PhoneCodeVO oldPhoneCode = systemUserCacheDAO.getHash(DIYKey.getMobilePhoneCodeKey(systemUser.getMobilePhone()),
				PhoneCodeVO.class);
		if (StringUtils.isNoneBlank(systemUserEditVO.getOldPhoneCode()) && !oldPhoneCode.getCode().equals(systemUserEditVO.getOldPhoneCode())) {
			throw new MobilePhoneCodeErrorException("验证码不一致");
		}
		
		if (StringUtils.isNoneBlank(systemUserEditVO.getOldPhoneCode()) && oldPhoneCode.getTimestamp() < new Date().getTime()) {
			throw new MobilePhoneCodeTimeoutException("验证码已过期");
		}
		//若更换手机
		if(systemUserEditVO.getIsUpdateMobilePhone() != 0){
			PhoneCodeVO newPhoneCode = systemUserCacheDAO.getHash(DIYKey.getMobilePhoneCodeKey(systemUserEditVO.getMobilePhone()),
					PhoneCodeVO.class);
			SystemUser user = systemUserDAO.findByMobilePhone(systemUserEditVO.getMobilePhone());
			if (!newPhoneCode.getCode().equals(systemUserEditVO.getNewPhoneCode())) {
				throw new MobilePhoneCodeErrorException("验证码不一致");
			}
			
			if (newPhoneCode.getTimestamp() < new Date().getTime()) {
				throw new MobilePhoneCodeTimeoutException("验证码已过期");
			}
			if (user != null && !user.getId().equals(id)) {
				throw new MobilePhoneHasUsedException("该手机已经绑定其他账户");
			}
		}
		if(systemUserEditVO.getIsUpdatePassword() == Is.YES.toIntValue()){
			String MD5password = EncryptMD5Util.getMD5(password);
			systemUser.setPassword(MD5password);
		}
		systemUser.setMobilePhone(mobilePhone);
		systemUser.setName(name);
		systemUser.setEmail(email);
		systemUser.setGender(systemUserEditVO.getGender());
		
		if(systemUser.getIsUpdatePassword() != Is.YES.toIntValue()){
			systemUser.setIsUpdatePassword(systemUserEditVO.getIsUpdatePassword());
		}
		
		//移除cookies
		SystemUserSessionVO systemUserSessionVO = systemUserCacheDAO
				.getHash(DIYKey.getSessionHashKey(systemUserEditVO.getSessionId()), SystemUserSessionVO.class);
		
//		CookieUtils.setCookie(response,	Constants.ACCESS_TOKEN_SESSION, systemUserSessionVO.getSessionId());
//		CookieUtils.setCookie(response,	Constants.SYSTEM_ID, systemUserSessionVO.getSystemId());
//		CookieUtils.setCookie(response, Constants.LOGIN_TYPE, systemUserSessionVO.getLoginType().toString());
		
		systemUserDAO.update(systemUser);
		//若修改手机号（账号）或密码则需要重新登陆
		if(systemUserEditVO.getIsUpdateMobilePhone() == Is.YES.toIntValue() || systemUserEditVO.getIsUpdatePassword() == Is.YES.toIntValue()){
			String key = DIYKey.getSessionHashKey(systemUserEditVO.getSessionId());
			systemUserCacheDAO.del(key);
		}
		
		return result;
	}

	@Override
	public SystemUser findBySessionId(String sessionId) {
		SystemUserSessionVO systemUserSessionVO = systemUserCacheDAO
				.getHash(DIYKey.getSessionHashKey(sessionId), SystemUserSessionVO.class);
		SystemUser systemUser= systemUserDAO.query(systemUserSessionVO.getSystemUserId());
		if (systemUser == null) {
			throw new SystemUserNotFoundException("该用户不存在！");
		}
		systemUser.setPassword(null);
		return systemUser;
	}
	
	@Override
	public ResultTO addAgent(SystemUser sysUser) {
		SystemUserTO sysUserTO = new SystemUserTO();
		
		SystemUser oldUser = systemUserDAO.findBySystemId(sysUser.getSystemId(), SystemUserType.OPERATION.toIntStatus());
		if(oldUser != null) {
			// 重复提交
			BeanUtils.copyProperties(oldUser, sysUserTO);
			return new ResultTO(sysUserTO);
		}
		
		sysUser.setStatus(SystemUserStatus.INACTIVE.toIntStatus()); // 新增时停用状态, 需要管理员去点激活按钮
		sysUser.setPlatform(SystemUserType.OPERATION.toIntStatus());
		sysUser.setIsMainAccount(0);
		sysUser.setIsAuth(0);
		sysUser.setIsUpdatePassword(0);
		sysUser.setSafetyLevel(0);
		
		systemUserDAO.insert(sysUser);

		BeanUtils.copyProperties(sysUser, sysUserTO);
		return new ResultTO(sysUserTO);
	}
	
	@Override
	public ResultVO switchActivationStatus(String systemId, int status) {
		SystemUser sysUser = systemUserDAO.findBySystemId(systemId, SystemUserType.OPERATION.toIntStatus());
		if(sysUser == null) {
			throw new SystemUserNotFoundException("该用户不存在！");
		}
		
		ResultVO result = new ResultVO();
		SystemUserStatus statusEnum = SystemUserStatus.toFlag(status);
		
		ResultTO rTO = agentFeignService.switchActivationStatus(systemId, status);
		if(rTO.getStatus() != CMSCodeStatus.SUCCESS) {
			result.setStatus(rTO.getStatus());
			result.setMessage(rTO.getMessage());
			return result;
		}
		
		sysUser.setStatus(statusEnum.toIntStatus());
		systemUserDAO.update(sysUser);
		return result;
	}
	
	@Override
	public ResultTO updateAgent(SystemUser sysUser) {
		SystemUser thisUser = systemUserDAO.findBySystemId(sysUser.getSystemId(), SystemUserType.OPERATION.toIntStatus());
		if(thisUser == null) {
			throw new SystemUserNotFoundException("该用户不存在！");
		}
		
		thisUser.setName(sysUser.getName());
		thisUser.setMobilePhone(sysUser.getMobilePhone());
		thisUser.setGender(sysUser.getGender());
		thisUser.setEmail(sysUser.getEmail());
		systemUserDAO.update(thisUser);
		
		return new ResultTO(thisUser);
	}
	
	private TreeFunctionVO tree(List<? extends Function> dataList){
		// 节点列表（散列表，用于临时存储节点对象）  
		HashMap<String, TreeFunctionVO> nodeList = new HashMap<String, TreeFunctionVO>();  
		// 根节点  
		TreeFunctionVO root = new TreeFunctionVO();
		root.setName(Constants.ROOT_VALUE);
		root.setChildren(new ArrayList<TreeFunctionVO>());


		// 根据结果集构造节点列表（存入散列表）  
		for (Function function : dataList) { 
			TreeFunctionVO node = new TreeFunctionVO();
			BeanUtils.copyProperties(function, node);
			node.setChildren(new ArrayList<TreeFunctionVO>());
			nodeList.put(node.getId(), node);  
		}

		// 构造无序的多叉树
		Set<Entry<String, TreeFunctionVO>> entrySet = nodeList.entrySet();  
		for (Iterator<Entry<String, TreeFunctionVO>> it = entrySet.iterator(); it.hasNext();) {  
			TreeFunctionVO treeFunctionVO= it.next().getValue();

			if(Constants.ROOT_VALUE.equals(treeFunctionVO.getParentId())){
				root.getChildren().add(treeFunctionVO);
			}else{
				nodeList.get(treeFunctionVO.getParentId()).getChildren().add(treeFunctionVO); 
			}

		}
		
		// 对多叉树进行横向排序
		root.sortChildren();


		return root;
	}
}
